In this notebook, you will compile the visualizations from the previous analysis into functions that can be used for a Panel dashboard.
# imports
import panel as pn
pn.extension('plotly')
import plotly.express as px
import pandas as pd
import hvplot.pandas
import matplotlib.pyplot as plt
import os
from pathlib import Path
from dotenv import load_dotenv
# Read the Mapbox API key
load_dotenv()
map_box_api = os.getenv("mapbox")
px.set_mapbox_access_token(map_box_api)
# Import the necessary CSVs to Pandas DataFrames
file_path = Path("Data/sfo_neighborhoods_census_data.csv")
sfo_data = pd.read_csv(file_path, index_col="year")
sfo_data.head()
| neighborhood | sale_price_sqr_foot | housing_units | gross_rent | |
|---|---|---|---|---|
| year | ||||
| 2010 | Alamo Square | 291.182945 | 372560 | 1239 |
| 2010 | Anza Vista | 267.932583 | 372560 | 1239 |
| 2010 | Bayview | 170.098665 | 372560 | 1239 |
| 2010 | Buena Vista Park | 347.394919 | 372560 | 1239 |
| 2010 | Central Richmond | 319.027623 | 372560 | 1239 |
file_path = Path("Data/neighborhoods_coordinates.csv")
sfo_data = pd.read_csv(file_path)
sfo_data.head()
| Neighborhood | Lat | Lon | |
|---|---|---|---|
| 0 | Alamo Square | 37.791012 | -122.402100 |
| 1 | Anza Vista | 37.779598 | -122.443451 |
| 2 | Bayview | 37.734670 | -122.401060 |
| 3 | Bayview Heights | 37.728740 | -122.410980 |
| 4 | Bernal Heights | 37.728630 | -122.443050 |
file_path2 = Path("housing_units_per_year.csv")
data_group_per_year = pd.read_csv(file_path2)
data_group_per_year.columns= ['year','housing_units']
data_group_per_year .head(10)
| year | housing_units | |
|---|---|---|
| 0 | 2011 | 374507 |
| 1 | 2012 | 376454 |
| 2 | 2013 | 378401 |
| 3 | 2014 | 380348 |
| 4 | 2015 | 382295 |
| 5 | 2016 | 384242 |
file_path3 = Path("Average_of_housing_Cost_per_year.csv")
Average_of_housing_Cost_per_year = pd.read_csv(file_path3)
Average_of_housing_Cost_per_year.columns= ['year','sale_price_sqr_foot', 'gross_rent']
Average_of_housing_Cost_per_year.head(10)
| year | sale_price_sqr_foot | gross_rent | |
|---|---|---|---|
| 0 | 2010 | 369.344353 | 1239 |
| 1 | 2011 | 341.903429 | 1530 |
| 2 | 2012 | 399.389968 | 2324 |
| 3 | 2013 | 483.600304 | 2971 |
| 4 | 2014 | 556.277273 | 3528 |
| 5 | 2015 | 632.540352 | 3739 |
| 6 | 2016 | 697.643709 | 4390 |
file_path4 = Path("costs.csv")
df_costs = pd.read_csv(file_path4)
#df_costs.columns= ['year','neighborhood','sale_price_sqr_foot','housing_units' ,'gross_rent']
df_costs.head(10)
| year | neighborhood | sale_price_sqr_foot | housing_units | gross_rent | |
|---|---|---|---|---|---|
| 0 | 2010 | Alamo Square | 291.182945 | 372560 | 1239 |
| 1 | 2010 | Anza Vista | 267.932583 | 372560 | 1239 |
| 2 | 2010 | Bayview | 170.098665 | 372560 | 1239 |
| 3 | 2010 | Buena Vista Park | 347.394919 | 372560 | 1239 |
| 4 | 2010 | Central Richmond | 319.027623 | 372560 | 1239 |
| 5 | 2010 | Central Sunset | 418.172493 | 372560 | 1239 |
| 6 | 2010 | Corona Heights | 369.359338 | 372560 | 1239 |
| 7 | 2010 | Cow Hollow | 569.379968 | 372560 | 1239 |
| 8 | 2010 | Croker Amazon | 165.645730 | 372560 | 1239 |
| 9 | 2010 | Diamond Heights | 456.930822 | 372560 | 1239 |
file_path5 = Path("top_ten.csv")
top_ten = pd.read_csv(file_path5)
top_ten.head(10)
| neighborhood | sale_price_sqr_foot | housing_units | gross_rent | |
|---|---|---|---|---|
| 0 | Union Square District | 903.993258 | 377427.50 | 2555.166667 |
| 1 | Merced Heights | 788.844818 | 380348.00 | 3414.000000 |
| 2 | Miraloma Park | 779.810842 | 375967.25 | 2155.250000 |
| 3 | Pacific Heights | 689.555817 | 378401.00 | 2817.285714 |
| 4 | Westwood Park | 687.087575 | 382295.00 | 3959.000000 |
| 5 | Telegraph Hill | 676.506578 | 378401.00 | 2817.285714 |
| 6 | Presidio Heights | 675.350212 | 378401.00 | 2817.285714 |
| 7 | Cow Hollow | 665.964042 | 378401.00 | 2817.285714 |
| 8 | Potrero Hill | 662.013613 | 378401.00 | 2817.285714 |
| 9 | South Beach | 650.124479 | 375805.00 | 2099.000000 |
file_path6 = Path("most_expensive.csv")
most_expensive = pd.read_csv(file_path6)
most_expensive.head(10)
| year | neighborhood | sale_price_sqr_foot | housing_units | gross_rent | |
|---|---|---|---|---|---|
| 0 | 2010 | Cow Hollow | 569.379968 | 372560 | 1239 |
| 1 | 2010 | Miraloma Park | 680.608729 | 372560 | 1239 |
| 2 | 2010 | Pacific Heights | 496.516014 | 372560 | 1239 |
| 3 | 2010 | Potrero Hill | 491.450004 | 372560 | 1239 |
| 4 | 2010 | Presidio Heights | 549.417931 | 372560 | 1239 |
| 5 | 2010 | South Beach | 1037.099789 | 372560 | 1239 |
| 6 | 2010 | Telegraph Hill | 524.793509 | 372560 | 1239 |
| 7 | 2010 | Union Square District | 569.193448 | 372560 | 1239 |
| 8 | 2011 | Cow Hollow | 390.595653 | 374507 | 1530 |
| 9 | 2011 | Miraloma Park | 414.676065 | 374507 | 1530 |
file_path7 = Path("combined_df.csv")
combined_df = pd.read_csv(file_path7)
combined_df.head(10)
| Neighborhood | Lat | Lon | neighborhood | sale_price_sqr_foot | housing_units | gross_rent | |
|---|---|---|---|---|---|---|---|
| 0 | Alamo Square | 37.791012 | -122.402100 | Alamo Square | 366.020712 | 378401.0 | 2817.285714 |
| 1 | Anza Vista | 37.779598 | -122.443451 | Anza Vista | 373.382198 | 379050.0 | 3031.833333 |
| 2 | Bayview | 37.734670 | -122.401060 | Bayview | 204.588623 | 376454.0 | 2318.400000 |
| 3 | Bayview Heights | 37.728740 | -122.410980 | Bayview Heights | 590.792839 | 382295.0 | 3739.000000 |
| 4 | Bernal Heights | 37.728630 | -122.443050 | Bernal Heights | 576.746488 | 379374.5 | 3080.333333 |
| 5 | Buena Vista Park | 37.768160 | -122.439330 | Buena Vista Park | 452.680591 | 378076.5 | 2698.833333 |
| 6 | Central Richmond | 37.777890 | -122.445170 | Central Richmond | 394.422399 | 378401.0 | 2817.285714 |
| 7 | Central Sunset | 37.749610 | -122.489990 | Central Sunset | 423.687928 | 378401.0 | 2817.285714 |
| 8 | Clarendon Heights | 37.753310 | -122.447030 | Clarendon Heights | 487.244886 | 376454.0 | 2250.500000 |
| 9 | Corona Heights | 37.785530 | -122.456000 | Corona Heights | 587.539067 | 377232.8 | 2472.000000 |
In this section, you will copy the code for each plot type from your analysis notebook and place it into separate functions that Panel can use to create panes for the dashboard.
These functions will convert the plot object to a Panel pane.
Be sure to include any DataFrame transformation/manipulation code required along with the plotting code.
Return a Panel pane object from each function that can be used to build the dashboard.
Note: Remove any .show() lines from the code. We want to return the plots instead of showing them. The Panel dashboard will then display the plots.
# Define Panel Visualization Functions
def housing_units_per_year():
"""Housing Units Per Year."""
fig_housing_units = plt.figure()
plot_housing_units = data_group_per_year.plot.bar()
plot_housing_units.set_xlabel('Year', fontsize=12)
plot_housing_units.set_ylabel('Housing Units', fontsize=12)
plot_housing_units.set_title("Housing Units in San Francisco from 2010 to 2016", fontsize=15, fontweight='bold')
housing_units_std =data_group_per_year.std()
housing_units_min =min(data_group_per_year)
housing_units_max =max(data_group_per_year)
plot_housing_units.set_ylim(370000, 390000)
plt.show()
plt.close(fig_housing_units)
return plot_housing_units
housing_units_per_year()
<Figure size 432x288 with 0 Axes>
<matplotlib.axes._subplots.AxesSubplot at 0x258a657a820>
# Define Panel Visualization Functions
def average_gross_rent():
"""Average Gross Rent in San Francisco Per Year."""
fig_Average_of_housing_Cost_per_year = plt.figure()
plot_Average_of_housing_Cost_per_year = Average_of_housing_Cost_per_year['gross_rent'].plot(color = 'red')
plot_Average_of_housing_Cost_per_year.set_xlabel('Year', fontsize=12)
plot_Average_of_housing_Cost_per_year.set_ylabel('Gross Rent', fontsize=12)
plot_Average_of_housing_Cost_per_year.set_title("Average Gross Rent by Year, San Francisco", fontsize=15, fontweight='bold')
plt.show()
plt.close(fig_Average_of_housing_Cost_per_year)
return plot_Average_of_housing_Cost_per_year
average_gross_rent()
<matplotlib.axes._subplots.AxesSubplot at 0x258a6623160>
# Define Panel Visualization Functions
def average_sales_price():
"""Average Sales Price Per Year."""
fig_Average_of_housing_Cost_per_year = plt.figure()
plot_Average_of_housing_Cost_per_year = Average_of_housing_Cost_per_year['sale_price_sqr_foot'].plot(color = 'purple')
plot_Average_of_housing_Cost_per_year.set_xlabel('Year', fontsize=12)
plot_Average_of_housing_Cost_per_year.set_ylabel('Price per SqFt', fontsize=12)
plot_Average_of_housing_Cost_per_year.set_title("Average Sale Price per sqrfoot by Year, San Francisco", fontsize=15, fontweight='bold')
plt.show()
plt.close(fig_Average_of_housing_Cost_per_year)
return plot_Average_of_housing_Cost_per_year
average_sales_price()
<matplotlib.axes._subplots.AxesSubplot at 0x258a66f1850>
# Define Panel Visualization Functions
def average_price_by_neighborhood():
"""Average Prices by Neighborhood."""
average_price_by_neighborhood = df_costs.hvplot.line(x='year',
y=['sale_price_sqr_foot'],
groupby=(['neighborhood']),
rot=90).opts(yformatter="%.0f",
title="Average Price per sq ft.",
ylabel = 'Average sale_price_sqr_foot',
xlabel='Year')
return average_price_by_neighborhood
average_price_by_neighborhood()
# Define Panel Visualization Functions
def top_most_expensive_neighborhoods():
"""Top 10 Most Expensive Neighborhoods."""
top_most_expensive_neighborhoods = top_ten.hvplot.bar(x='neighborhood',y='sale_price_sqr_foot',ylim=(500.0000 , 950.0000),
rot=90).opts(yformatter="%.0f",
title="The top 10 Most Expensive Neighborhoodsin San Francisco from 2010 to 2016")
return top_most_expensive_neighborhoods
# Define Panel Visualization Functions
def most_expensive_neighborhoods_rent_sales():
"""Comparison of Rent and Sales Prices of Most Expensive Neighborhoods."""
most_expensive_neighborhoods_rent_sales = df_costs.hvplot.bar('year', y=['gross_rent','sale_price_sqr_foot'],
groupby=(['neighborhood']),
rot=90).opts(yformatter="%.0f",
title="Top 10 Expensive Neighborhood in San Francisco from 2010 to 2016",
ylabel = 'Housing Units',
xlabel='Neighborhood')
return most_expensive_neighborhoods_rent_sales
# Define Panel Visualization Functions
def parallel_coordinates():
"""Parallel Coordinates Plot."""
parallel_coordinates = px.parallel_coordinates(top_ten, color='sale_price_sqr_foot',
title="Parallel Categories Plot of Most Expensive Neighborhoods in San Francisco per year")
return parallel_coordinates
# Define Panel Visualization Functions
def parallel_categories():
"""Parallel Categories Plot."""
parallel_categories= px.parallel_categories(
top_ten,
dimensions=["neighborhood", "housing_units", "gross_rent"],
color="sale_price_sqr_foot",
color_continuous_scale=px.colors.sequential.Inferno,
title="Parallel Categories Plot of Most Expensive Neighborhoods in San Francisco per year",
labels={
"type": "Neighborhood",
"region": "Housing Units",
"prop_size": "Gross Rent",
}
)
return parallel_categories
# Define Panel Visualization Functions
def neighborhood_map():
"""Neighborhood Map."""
map_box = px.scatter_mapbox(
combined_df,
lat="Lat",
lon="Lon",
size="sale_price_sqr_foot",
color="gross_rent",
zoom=4,
title= "Average Values per Neighborhood in San Francisco")
map_box.update_layout(
mapbox_style="carto-positron")
map_box.show()
return map_box
# Define Panel Visualization Functions
def neighborhood_map(test=True):
"""Neighborhood Map."""
map_box = px.scatter_mapbox(
combined_df,
lat="Lat",
lon="Lon",
size="sale_price_sqr_foot",
color="gross_rent",
zoom=4,
title= "Average Values per Neighborhood in San Francisco")
if test:
map_box.update_layout(
mapbox_style="carto-positron")
map_box.show()
return map_box
neighborhood_map(test=False)
# Define Panel Visualization Functions
def sunburst():
"""Sunburst Plot."""
sunburst = px.sunburst(most_expensive, path=['year', 'neighborhood'],
values='gross_rent', color='gross_rent',
color_continuous_scale=px.colors.sequential.Blues,
height=600,
title="Sunburst Chart of Most Expensive Neighborhoods in San Francisco per year")
return sunburst
In this section, you will combine all of the plots into a single dashboard view using Panel. Be creative with your dashboard design!
House_avg_price = pn.Row(housing_units_per_year(), average_price_by_neighborhood())
House_avg_rent_sales = pn.Row( average_gross_rent(), average_sales_price())
Expensive_Houses = pn.Row( top_most_expensive_neighborhoods(), most_expensive_neighborhoods_rent_sales())
Parallel_Cat = pn.Row(parallel_coordinates(), parallel_categories())
<Figure size 432x288 with 0 Axes>
# Create a Title for the Dashboard
SF_Housing = pn.Column(
"## San Francisco Housing Cost Analysis",
#neighborhood_map(),
House_avg_price,
House_avg_rent_sales)
SF_Most_Expensive = pn.Column(
"## Most Expensive Houses in San Francisco",
Expensive_Houses,
Parallel_Cat,
sunburst())
# Create a tab layout for the dashboard
San_Francisco_Housing_Cost_Analysis_pop_dasboard = pn.Tabs(
( "SF_Housing",SF_Housing),
("SF_Most_Expensive",SF_Most_Expensive))
San_Francisco_Housing_Cost_Analysis_pop_dasboard
AxesSubplot(0.125,0.125;0.775x0.755)
AxesSubplot(0.125,0.125;0.775x0.755)
AxesSubplot(0.125,0.125;0.775x0.755)
# Serve the dashboard
San_Francisco_Housing_Cost_Analysis_pop_dasboard.servable()
AxesSubplot(0.125,0.125;0.775x0.755)
AxesSubplot(0.125,0.125;0.775x0.755)
AxesSubplot(0.125,0.125;0.775x0.755)
Note: Some of the Plotly express plots may not render in the notebook through the panel functions.
However, you can test each plot by uncommenting the following code
housing_units_per_year()
<Figure size 432x288 with 0 Axes>
<matplotlib.axes._subplots.AxesSubplot at 0x2589f8d88b0>
average_gross_rent()
<matplotlib.axes._subplots.AxesSubplot at 0x258a6739af0>
average_sales_price()
<matplotlib.axes._subplots.AxesSubplot at 0x258a895b160>
average_price_by_neighborhood()
top_most_expensive_neighborhoods()
most_expensive_neighborhoods_rent_sales()
neighborhood_map(test=False)
neighborhood_map()
parallel_categories()
parallel_coordinates()
sunburst()